package request

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"maps"
	"net/http"
	"slices"
	"strconv"
	"strings"
	"vector/tools"
)

// VectorTask 向量检索任务实现（模式1）
type VectorTask struct {
	content         string
	provinceName    string
	knowledgeString string
	atomString      string
	resultData      map[string]any
}

func (v *VectorTask) Reset() {
	v.content = ""
	v.knowledgeString = ""
	v.atomString = ""
	v.provinceName = ""
	clear(v.resultData)

}

// NewTaskData 初始化任务数据
func (v *VectorTask) NewTaskData(row map[string]any) error {
	v.resultData = maps.Clone(row)

	requiredFields := map[string]*string{
		"问题":   &v.content,
		"知识标题": &v.knowledgeString,
		"原子名称": &v.atomString,
	}

	// 统一处理必填字段
	for field, target := range requiredFields {
		if value, ok := row[field]; ok {
			*target = value.(string)
		} else {
			errMsg := fmt.Sprintf("缺少%s参数", field)
			v.resultData["备注"] = errMsg
			return fmt.Errorf(errMsg)
		}
	}

	// 处理省份字段（有默认值）
	if provinceName, ok := row["省份"]; ok {
		v.provinceName = provinceName.(string)
	} else {
		v.provinceName = "安徽" // 默认省份
	}

	return nil
}

// Do 执行向量检索任务
func (v *VectorTask) Do() {
	topNIndexList := tools.Config.Excel.TopN()

	// 格式化知识
	knowledgeList := KnowledgeFormat(v.knowledgeString, v.atomString, false)
	total, _ := strconv.Atoi(knowledgeList["total"][0])

	iflytek := IflytekVector{
		accuracyAtom: make([]string, len(topNIndexList)),
		accuracy:     make([]float64, len(topNIndexList)),
	}
	iflytek.note = iflytek.NewRequest(v.content, v.provinceName)
	iflytek.note = iflytek.Calculation(total, topNIndexList, knowledgeList)

	result := iflytek.Print(total, topNIndexList)

	// 将结果合并到resultData中
	for key, value := range result {
		v.resultData[key] = value
	}
}

// Result 返回任务结果
func (v *VectorTask) Result() map[string]any {
	return maps.Clone(v.resultData)
}

// VectorAnalysisTask 向量分析任务实现（模式2 - 本地分析）
type VectorAnalysisTask struct {
	topString       string
	knowledgeString string
	atomString      string
	resultData      map[string]any
}

func (v *VectorAnalysisTask) Reset() {
	v.topString = ""
	v.knowledgeString = ""
	v.atomString = ""
	clear(v.resultData)
}

// NewTaskData 初始化任务数据
func (v *VectorAnalysisTask) NewTaskData(row map[string]any) error {
	v.resultData = maps.Clone(row)

	requiredFields := map[string]*string{
		"TOP 10": &v.topString,
		"知识标题":   &v.knowledgeString,
		"原子名称":   &v.atomString,
	}

	// 统一处理必填字段
	for field, target := range requiredFields {
		if value, ok := row[field]; ok {
			*target = value.(string)
		} else {
			errMsg := fmt.Sprintf("缺少%s参数", field)
			v.resultData["备注"] = errMsg
			return fmt.Errorf(errMsg)
		}
	}

	return nil
}

// Do 执行向量分析任务
func (v *VectorAnalysisTask) Do() {
	topNIndexList := tools.Config.Excel.TopN()

	// 格式化知识
	knowledgeList := KnowledgeFormat(v.knowledgeString, v.atomString, false)
	total, _ := strconv.Atoi(knowledgeList["total"][0])

	iflytek := IflytekVector{
		accuracyAtom: make([]string, len(topNIndexList)),
		accuracy:     make([]float64, len(topNIndexList)),
	}
	iflytek.note = iflytek.TopStringToXfData(v.topString, "")
	iflytek.note = iflytek.Calculation(total, topNIndexList, knowledgeList)

	result := iflytek.Print(total, topNIndexList)

	// 将结果合并到resultData中
	for key, value := range result {
		v.resultData[key] = value
	}
}

// Result 返回任务结果
func (v *VectorAnalysisTask) Result() map[string]any {
	return maps.Clone(v.resultData)
}

// VectorAccuracyTask 向量准确率任务实现（模式5）
type VectorAccuracyTask struct {
	content       string
	provinceName  string
	knowledgeList string
	resultData    map[string]any
}

func (v *VectorAccuracyTask) Reset() {
	v.content = ""
	v.provinceName = ""
	v.knowledgeList = ""
	clear(v.resultData)
}

// NewTaskData 初始化任务数据
func (v *VectorAccuracyTask) NewTaskData(row map[string]any) error {
	v.resultData = maps.Clone(row)

	requiredFields := map[string]*string{
		"问题": &v.content,
		"知识": &v.knowledgeList,
	}

	// 统一处理必填字段
	for field, target := range requiredFields {
		if value, ok := row[field]; ok {
			*target = value.(string)
		} else {
			errMsg := fmt.Sprintf("缺少%s参数", field)
			v.resultData["备注"] = errMsg
			return fmt.Errorf(errMsg)
		}
	}

	// 处理省份字段（有默认值）
	if provinceName, ok := row["省份"]; ok {
		v.provinceName = provinceName.(string)
	} else {
		v.provinceName = "安徽" // 默认省份
	}

	return nil
}

// Do 执行向量准确率任务
func (v *VectorAccuracyTask) Do() {
	topNIndexList := tools.Config.Excel.TopN()
	iflytek := IflytekVector{
		accuracyAtom: make([]string, len(topNIndexList)),
		accuracy:     make([]float64, len(topNIndexList)),
	}
	iflytek.note = iflytek.NewRequest(v.content, v.provinceName)

	result := map[string]any{
		"备注": iflytek.note,
	}
	if iflytek.note != nil {
		// 将结果合并到resultData中
		for key, value := range result {
			v.resultData[key] = value
		}
		return
	}

	// 格式化knowledgeListString
	knowledgeList := KnowledgeFormat(v.knowledgeList, "", true)

	var flg bool
	var scoreList, badScoreList []float64
	// 遍历向量结果
	for index, atomItem := range iflytek.Data {
		// 截取原子内容
		if tools.Config.InterceptNum > 0 && tools.Config.InterceptNum < len(atomItem.Content) {
			atomItem.Content = atomItem.Content[:tools.Config.InterceptNum]
		}
		if index < 10 {
			scoreList = append(scoreList, atomItem.Score)
		} else if index >= 30 {
			badScoreList = append(badScoreList, atomItem.Score)
		}

		// 拼接top10
		iflytek.topString.WriteString(fmt.Sprintf("TOP%d:\n%s\n", index+1, atomItem.topString()))

		// 判断是否命中
		if atomList, ok := knowledgeList[atomItem.KnowledgeName]; ok {
			if slices.Contains(atomList, atomItem.GroupName) {
				flg = true
			}
		}
	}
	jsonBytesScoreList, _ := json.Marshal(scoreList)
	jsonBytesBadScoreList, _ := json.Marshal(badScoreList)
	result["TOP 10"] = iflytek.topString.String()
	result["是否命中"] = flg
	result["正例"] = string(jsonBytesScoreList)
	result["负例"] = string(jsonBytesBadScoreList)

	// 将结果合并到resultData中
	for key, value := range result {
		v.resultData[key] = value
	}
}

// Result 返回任务结果
func (v *VectorAccuracyTask) Result() map[string]any {
	return maps.Clone(v.resultData)
}

// ExternalVectorTask 外部向量接口任务实现（模式3）
type ExternalVectorTask struct {
	content      string
	provinceName string
	resultData   map[string]any
}

func (e *ExternalVectorTask) Reset() {
	e.content = ""
	e.provinceName = ""
	clear(e.resultData)
}

// NewTaskData 初始化任务数据
func (e *ExternalVectorTask) NewTaskData(row map[string]any) error {
	e.resultData = maps.Clone(row)

	// 获取必要参数
	if content, ok := row["问题"]; ok {
		e.content = content.(string)
	} else {
		e.resultData["备注"] = "缺少问题参数"
		return fmt.Errorf("缺少问题参数")
	}

	if provinceName, ok := row["省份"]; ok {
		e.provinceName = provinceName.(string)
	} else {
		e.provinceName = "安徽" // 默认省份
	}

	return nil
}

// Do 执行外部向量接口任务
func (e *ExternalVectorTask) Do() {
	result := map[string]any{
		"TOP 10": "",
		"备注":     "",
	}

	// 读取默认请求参数
	var param = make(map[string]any)
	tools.MapCopy(param, tools.Config.Vector.KmExt.Body)

	param["questionWord"] = strings.TrimSpace(e.content)

	// 设置省份code
	if provinceCode, err := tools.Config.Account.GetProvinceCode(e.provinceName); err != nil {
		result["备注"] = err.Error()

		// 将结果合并到resultData中
		for key, value := range result {
			e.resultData[key] = value
		}
		return
	} else {
		param["scope"] = provinceCode
	}

	// map to json string
	body, err := json.Marshal(map[string]any{"params": param})
	if err != nil {
		result["备注"] = err.Error()

		// 将结果合并到resultData中
		for key, value := range result {
			e.resultData[key] = value
		}
		return
	}

	client := &http.Client{}
	// 创建POST请求
	request, _ := http.NewRequest(
		"POST",
		"http://ngkm.cs.cmos/ngkm/ws/externalKmVectorSearch/vectorSearchByKeyWordsNew",
		bytes.NewBuffer(body),
	)

	// 设置Header
	for key, value := range tools.Config.Vector.KmExt.Header {
		request.Header.Set(key, value)
	}

	// 发送请求
	resp, err := client.Do(request)
	if err != nil {
		result["备注"] = err.Error()

		// 将结果合并到resultData中
		for key, value := range result {
			e.resultData[key] = value
		}
		return
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)

	ex := new(extVectorSearchResponse)
	_ = json.Unmarshal(respBody, ex)

	// 分析响应结果
	if ex.RtnCode != "0" {
		result["备注"] = "返回code码异常 ->" + string(respBody)

		// 将结果合并到resultData中
		for key, value := range result {
			e.resultData[key] = value
		}
		return
	}

	// top10数据
	top10 := ""
	var score float64
	for index, knwlgItem := range ex.Beans {
		// 拼接top10
		top10 += fmt.Sprintf("TOP%d:\n知识名称：%s\n", index+1, knwlgItem.KnowledgeName)
		for i, grpng := range knwlgItem.GrpngList {
			top10 += fmt.Sprintf("原子组名称-%d：%s\n", i+1, grpng.GrpngNm)
			top10 += fmt.Sprintf("原子组相识度-%d：%s\n", i+1, grpng.Similarity)

			groupContent := grpng.String()
			// 截取原子内容
			if tools.Config.InterceptNum > 0 && tools.Config.InterceptNum < len(groupContent) {
				groupContent = groupContent[:tools.Config.InterceptNum]
			}
			top10 += fmt.Sprintf("原子组内容-%d：%s\n", i+1, groupContent)

			// 统计相似度
			if i == 0 {
				switch v := grpng.Similarity.(type) {
				case float64:
					score = v
				case string:
					score, _ = strconv.ParseFloat(v, 64)
				case int64:
					score = float64(v)
				case int:
					score = float64(v)
				}
			}
		}
	}
	result["TOP 10"] = top10
	result["Similarity"] = score

	// 将结果合并到resultData中
	for key, value := range result {
		e.resultData[key] = value
	}
}

// Result 返回任务结果
func (e *ExternalVectorTask) Result() map[string]any {
	return maps.Clone(e.resultData)
}

// extVectorSearchResponse 外部向量搜索响应结构
type extVectorSearchResponse struct {
	RtnCode string             `json:"rtnCode"`
	Beans   []extKnowledgeItem `json:"beans"`
}

// extKnowledgeItem 外部知识项结构
type extKnowledgeItem struct {
	KnowledgeId   string     `json:"knowledgeId"`
	KnowledgeName string     `json:"knowledgeName"`
	GrpngList     []extGrpng `json:"grpngList"`
}

// extGrpng 外部原子组结构
type extGrpng struct {
	GrpngNm    string              `json:"grpngNm"`
	Similarity any                 `json:"similarity"`
	AtomList   []map[string]string `json:"atomList"`
}

// String 格式化输出原子组内容
func (g *extGrpng) String() string {
	var result string
	for _, v := range g.AtomList {
		result += fmt.Sprintf("%s###%s\n", v["paramName"], v["unrichcontent"])
	}
	return result
}
